home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / lfs / lfsMain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  16.0 KB  |  593 lines

  1. /* 
  2.  * lfsMain.c --
  3.  *
  4.  *    Routines for attaching and detaching LFS file systems.
  5.  *
  6.  * Copyright 1989 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/lfs/lfsMain.c,v 1.14 92/03/19 17:31:57 jhh Exp $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20. #include <sprite.h>
  21. #include <lfs.h>
  22. #include <lfsInt.h>
  23. #include <stdlib.h>
  24. #include <fsioDevice.h>
  25. #include <fsdm.h>
  26. #include <proc.h>
  27. #include <string.h>
  28. #include <fsCmd.h>
  29.  
  30.  
  31. typedef struct CheckPointData {
  32.     Lfs        *lfsPtr;    /* Lfs data structure of file system. */
  33.     Boolean    interval;    /* Set to TRUE if the checkpoint should
  34.                  * stop. */
  35. } CheckPointData;
  36.  
  37. static void CheckpointCallBack _ARGS_((ClientData clientData, 
  38.         Proc_CallInfo *callInfoPtr));
  39. static ReturnStatus GetDomainFromCmdArgs _ARGS_((int *bufSizePtr, 
  40.             char **bufferPtr, Fsdm_Domain **domainPtrPtr));
  41.  
  42.  
  43. /*
  44.  *----------------------------------------------------------------------
  45.  *
  46.  * Lfs_Init --
  47.  *
  48.  *    Initialized the modules of LFS.
  49.  *
  50.  * Results:
  51.  *    None.
  52.  *
  53.  * Side effects:
  54.  *    Memory may be allocated.
  55.  *
  56.  *----------------------------------------------------------------------
  57.  */
  58. void
  59. Lfs_Init() 
  60. {
  61.     LfsFileLayoutInit();
  62.     LfsDescMapInit();
  63.     LfsSegUsageInit();
  64.  
  65.     Fsdm_RegisterDiskManager("LFS", Lfs_AttachDisk);
  66. }
  67.  
  68. /*
  69.  *----------------------------------------------------------------------
  70.  *
  71.  * Lfs_AttachDomain --
  72.  *
  73.  *    Attach a LFS file system from the specified device. 
  74.  *
  75.  * Results:
  76.  *    SUCCESS if device is attached, FAILURE otherwise.
  77.  *
  78.  * Side effects:
  79.  *    LFS modules initialied if this is the first LFS attached.
  80.  *
  81.  *----------------------------------------------------------------------
  82.  */
  83.  
  84. ReturnStatus
  85. Lfs_AttachDisk(devicePtr, localName, flags, domainNumPtr)
  86.     Fs_Device    *devicePtr;    /* Device containing file system. */
  87.     char *localName;        /* The local prefix for the domain */
  88.     int  flags;            /* Attach flags. */
  89.     int *domainNumPtr;        /* OUT: Domain number allocated. */
  90. {
  91.     Lfs            *lfsPtr;
  92.     LfsDiskAddr        diskAddr;
  93.     ReturnStatus    status;
  94.     CheckPointData     *cpDataPtr;
  95.     /*
  96.      * Allocate space for the Lfs data structure fill in the fields need
  97.      * by the rest of the Lfs module to perform initialization correctly.
  98.      */
  99.     lfsPtr = (Lfs *) malloc(sizeof(*lfsPtr));
  100.     bzero((char *)lfsPtr, sizeof(*lfsPtr));
  101.     lfsPtr->devicePtr = devicePtr;
  102.     lfsPtr->name = localName;
  103.     lfsPtr->name = malloc(strlen(localName)+1);
  104.     lfsPtr->controlFlags = 0;
  105.     (void) strcpy(lfsPtr->name, localName);
  106.     lfsPtr->attachFlags = flags;
  107.  
  108.     /*
  109.      * Read the super block of the file system. Put a lot of trust in the
  110.      * magic number. 
  111.      */
  112.     LfsOffsetToDiskAddr(LFS_SUPER_BLOCK_OFFSET, &diskAddr);
  113.     status = LfsReadBytes(lfsPtr, diskAddr,  LFS_SUPER_BLOCK_SIZE,
  114.          (char *) &(lfsPtr->superBlock));
  115.     if (status != SUCCESS) {
  116.     free((char *) lfsPtr);
  117.     return status;
  118.     }
  119.     /*
  120.      * Validate the super block here.
  121.      */
  122.     if ((lfsPtr->superBlock.hdr.magic != LFS_SUPER_BLOCK_MAGIC) ||
  123.     (lfsPtr->superBlock.hdr.version != LFS_SUPER_BLOCK_VERSION)) {
  124.     free((char *) lfsPtr);
  125.     return FAILURE;
  126.     }
  127.     /*
  128.      * Check to make sure that the partition that the file system was
  129.      * built in matches the partition it is to be loaded from. To be
  130.      * backwards compatible we check the domainUID. If it's zero then
  131.      * the partition number isn't valid either. This check should go away
  132.      * once all lfs systems are upgraded to the new version of the 
  133.      * superblock.
  134.      */
  135.     if (lfsPtr->superBlock.hdr.domainUID != 0) {
  136.     if (lfsPtr->superBlock.hdr.partition != 
  137.         devicePtr->unit % FSDM_NUM_DISK_PARTS) {
  138.  
  139.         /* 
  140.          * File system was built on a different partition.
  141.          */
  142.         free((char *) lfsPtr);
  143.         return FAILURE;
  144.     }
  145.     }
  146.     lfsPtr->blockSizeShift = LfsLogBase2((unsigned)LfsBlockSize(lfsPtr));
  147.     lfsPtr->checkpointIntervalPtr = (int *) NIL;
  148.     Sync_LockInitDynamic(&(lfsPtr->lock), "LfsLock");
  149.     lfsPtr->activeFlags = 0;
  150.     lfsPtr->cleanerProcPtr = (Proc_ControlBlock *) NIL;
  151.     lfsPtr->dirModsActive = 0;
  152.     lfsPtr->numDirtyBlocks = 0;
  153.     status = LfsLoadFileSystem(lfsPtr, flags); 
  154.     if (status != SUCCESS) { 
  155.     free((char *)lfsPtr);
  156.     return status;
  157.     }
  158.     LfsMemInit(lfsPtr);
  159.     *domainNumPtr = lfsPtr->domainPtr->domainNumber;
  160.     /*
  161.      * Make our own copy of the prefix name.
  162.      */
  163.     lfsPtr->name = malloc(strlen(localName)+1);
  164.     (void) strcpy(lfsPtr->name, localName);
  165.     cpDataPtr = (CheckPointData *) malloc(sizeof(*cpDataPtr));
  166.     cpDataPtr->lfsPtr = lfsPtr;
  167.     cpDataPtr->interval = lfsPtr->superBlock.hdr.checkpointInterval *
  168.                 timer_IntOneSecond;
  169.  
  170.     lfsPtr->checkpointIntervalPtr = &(cpDataPtr->interval);
  171.  
  172.     Proc_CallFunc(CheckpointCallBack, (ClientData) cpDataPtr,
  173.             cpDataPtr->interval);
  174.     return status;
  175. }
  176.  
  177. /*
  178.  *----------------------------------------------------------------------
  179.  *
  180.  * Lfs_DetachDomain --
  181.  *
  182.  *    Detach a LFS file system domain.
  183.  *
  184.  * Results:
  185.  *    SUCCESS if device is detached, FAILURE otherwise.
  186.  *
  187.  * Side effects:
  188.  *
  189.  *----------------------------------------------------------------------
  190.  */
  191.  
  192. ReturnStatus
  193. Lfs_DetachDisk(domainPtr)
  194.      Fsdm_Domain *domainPtr;    /* Domain to detach. */
  195.  
  196. {
  197.     Lfs    *lfsPtr = LfsFromDomainPtr(domainPtr);
  198.     ReturnStatus status;
  199.  
  200.     status = LfsDetachFileSystem(lfsPtr);
  201.     LfsMemDetach(lfsPtr);
  202.     Fscache_UnregisterBackend(lfsPtr->domainPtr->backendPtr);
  203.     lfsPtr->domainPtr->backendPtr = (Fscache_Backend *) NIL;
  204.     Sync_LockClear(&lfsPtr->lock);
  205.     free(lfsPtr->name);
  206.     free((char *)lfsPtr);
  207.     return status;
  208. }
  209.  
  210.  
  211. /*
  212.  *----------------------------------------------------------------------
  213.  *
  214.  * Lfs_RereadSummaryInfo --
  215.  *
  216.  *    Reread the summary sector associated with the prefix and update
  217.  *    the domain information. This should be called if the summary
  218.  *    sector on the disk has been changed since the domain was attached.
  219.  *    LFS uses this call to reread the superBlock and get any changes made.
  220.  *
  221.  * Results:
  222.  *    SUCCESS 
  223.  *
  224.  * Side effects:
  225.  *
  226.  *----------------------------------------------------------------------
  227.  */
  228. /*ARGSUSED*/
  229. ReturnStatus
  230. Lfs_RereadSummaryInfo(domainPtr)
  231.     Fsdm_Domain        *domainPtr;    /* Domain to reread summary for. */
  232. {
  233.     Lfs    *lfsPtr = LfsFromDomainPtr(domainPtr);
  234.     LfsDiskAddr        diskAddr;
  235.     ReturnStatus status;
  236.     LfsSuperBlock    newSuperBlock;
  237.     /*
  238.      * Read the super block of the file system. Put a lot of trust in the
  239.      * magic number. 
  240.      */
  241.     LfsOffsetToDiskAddr(LFS_SUPER_BLOCK_OFFSET, &diskAddr);
  242.     status = LfsReadBytes(lfsPtr, diskAddr,  LFS_SUPER_BLOCK_SIZE,
  243.          (char *) &newSuperBlock);
  244.     if (status != SUCCESS) {
  245.     return status;
  246.     }
  247.     /*
  248.      * Validate the super block here.
  249.      */
  250.     if ((newSuperBlock.hdr.magic != LFS_SUPER_BLOCK_MAGIC) ||
  251.     (newSuperBlock.hdr.version != LFS_SUPER_BLOCK_VERSION)) {
  252.     return FAILURE;
  253.     }
  254.     /*
  255.      * Looks ok, update our incore version.
  256.      */
  257.     bcopy((char *) &newSuperBlock, (char *) &lfsPtr->superBlock,
  258.         sizeof(LfsSuperBlock));
  259.     return SUCCESS;
  260. }
  261.  
  262.  
  263.  
  264. /*
  265.  *----------------------------------------------------------------------
  266.  *
  267.  * Lfs_DomainWriteBack --
  268.  *
  269.  *    Force all domain information to disk.
  270.  *
  271.  * Results:
  272.  *    Error code if the write failed.
  273.  *
  274.  * Side effects:
  275.  *    None.
  276.  *
  277.  *----------------------------------------------------------------------
  278.  */
  279. ReturnStatus
  280. Lfs_DomainWriteBack(domainPtr, shutdown)
  281.     Fsdm_Domain    *domainPtr;    /* Domain to be written back. */
  282.     Boolean    shutdown;    /* TRUE if are syncing to shutdown the system.*/
  283. {
  284.     Lfs    *lfsPtr = LfsFromDomainPtr(domainPtr);
  285.  
  286.     return LfsCheckPointFileSystem(lfsPtr, LFS_CHECKPOINT_WRITEBACK);
  287.  
  288. }
  289.  
  290. /*
  291.  *----------------------------------------------------------------------
  292.  *
  293.  * GetDomainFromCmdArgs --
  294.  *
  295.  *    Return the Fsdm_Domain specified in the Lfs_Command arguments.
  296.  *    This routine updates the bufSize and bufferPtr to remove the
  297.  *    domain specifier argument.
  298.  *
  299.  * Results:
  300.  *    SUCCESS if domain fetched.
  301.  *
  302.  * Side effects:
  303.  *    None.
  304.  *
  305.  *----------------------------------------------------------------------
  306.  */
  307.  
  308.  
  309. static ReturnStatus
  310. GetDomainFromCmdArgs(bufSizePtr, bufferPtr, domainPtrPtr)
  311.     int    *bufSizePtr;    /* Size of Lfs_Command argument buffer. */
  312.     char **bufferPtr;    /* Argument buffer. */
  313.     Fsdm_Domain    **domainPtrPtr; /* OUT: Lfs Domain specified by arguments. */
  314. {
  315.     int        bufSize = (*bufSizePtr);
  316.     char    *buffer = (*bufferPtr);
  317.     int        domainNumber;
  318.     Fsdm_Domain    *domainPtr;
  319.  
  320.     if (bufSize < sizeof(int)) {
  321.     return GEN_INVALID_ARG;
  322.     }
  323.     bcopy(buffer, (char *) &domainNumber, sizeof(int));
  324.     domainPtr = Fsdm_DomainFetch(domainNumber, FALSE);
  325.     if (domainPtr == (Fsdm_Domain *) NIL) {
  326.     return GEN_INVALID_ARG;
  327.     }
  328.     if (domainPtr->domainOpsPtr->attachDisk != Lfs_AttachDisk) {
  329.     Fsdm_DomainRelease(domainNumber);
  330.     return GEN_INVALID_ARG;
  331.     }
  332.     (*domainPtrPtr) = domainPtr;
  333.     (*bufSizePtr) -= sizeof(int);
  334.     (*bufferPtr) += sizeof(int);
  335.     return SUCCESS;
  336. }
  337.  
  338. /*
  339.  *----------------------------------------------------------------------
  340.  *
  341.  * Lfs_Command --
  342.  *
  343.  *    Perform a user specified command on a LFS file system
  344.  *
  345.  * Results:
  346.  *    SUCCESS if the operation succeeded. An ReturnStatus otherwise.
  347.  *
  348.  * Side effects:
  349.  *    None.
  350.  *
  351.  *----------------------------------------------------------------------
  352.  */
  353.  
  354.  
  355. ReturnStatus
  356. Lfs_Command(command, bufSize, buffer)
  357.     int command;    /* Command to perform. */
  358.     int bufSize;    /* Size of the user's input/output buffer. */
  359.     Address buffer;    /* The user's input or output buffer. */
  360. {
  361.     Lfs    *lfsPtr;
  362.     ReturnStatus status;
  363.     Fsdm_Domain    *domainPtr;
  364.     char    *outBufferPtr = buffer;
  365.  
  366.     switch (command) {
  367.     case    FS_CLEAN_LFS_COMMAND: {
  368.         status = GetDomainFromCmdArgs(&bufSize, &buffer, &domainPtr);
  369.         if (status != SUCCESS) {
  370.         return status;
  371.         }
  372.         lfsPtr = (Lfs *) domainPtr->clientData;
  373.         LfsSegCleanStart(lfsPtr);
  374.         Fsdm_DomainRelease(domainPtr->domainNumber);
  375.         break;
  376.     }
  377.     case FS_SET_CONTROL_FLAGS_LFS_COMMAND: {
  378.         status = GetDomainFromCmdArgs(&bufSize, &buffer, &domainPtr);
  379.         if (status != SUCCESS) {
  380.         return status;
  381.         }
  382.         lfsPtr = (Lfs *) domainPtr->clientData;
  383.         if (bufSize >= sizeof(int)) {
  384.         bcopy(buffer, (char *) &(lfsPtr->controlFlags), sizeof(int));
  385.         } else {
  386.         status = GEN_INVALID_ARG;
  387.         }
  388.         Fsdm_DomainRelease(domainPtr->domainNumber);
  389.         break;
  390.     }
  391.     case FS_GET_CONTROL_FLAGS_LFS_COMMAND: {
  392.         status = GetDomainFromCmdArgs(&bufSize, &buffer, &domainPtr);
  393.         if (status != SUCCESS) {
  394.         return status;
  395.         }
  396.         lfsPtr = (Lfs *) domainPtr->clientData;
  397.         if (bufSize >= sizeof(int)) {
  398.         bcopy((char *) &(lfsPtr->controlFlags), outBufferPtr, 
  399.                 sizeof(int));
  400.         } else {
  401.         status = GEN_INVALID_ARG;
  402.         }
  403.         Fsdm_DomainRelease(domainPtr->domainNumber);
  404.         break;
  405.     }
  406.     case FS_FREE_FILE_NUMBER_LFS_COMMAND: {
  407.         int    fileNumber;
  408.         status = GetDomainFromCmdArgs(&bufSize, &buffer, &domainPtr);
  409.         if (status != SUCCESS) {
  410.         return status;
  411.         }
  412.         lfsPtr = (Lfs *) domainPtr->clientData;
  413.         if (bufSize >= sizeof(int)) {
  414.         bcopy(buffer, (char *) &fileNumber, sizeof(int));
  415.         printf("Lfs_FreeFileNumber(%s,%d)\n", lfsPtr->name, 
  416.                 fileNumber);
  417.         status = Lfs_FreeFileNumber(domainPtr, fileNumber);
  418.         } else {
  419.         status = GEN_INVALID_ARG;
  420.         }
  421.         Fsdm_DomainRelease(domainPtr->domainNumber);
  422.         return status;
  423.     }
  424.     case FS_ADJUST_SEG_USAGE_LFS_COMMAND: {
  425.         int    segNumber, activeBytes;
  426.         status = GetDomainFromCmdArgs(&bufSize, &buffer, &domainPtr);
  427.         if (status != SUCCESS) {
  428.         return status;
  429.         }
  430.         lfsPtr = (Lfs *) domainPtr->clientData;
  431.         if (bufSize >= sizeof(int)*2) {
  432.         bcopy(buffer, (char *) &segNumber, sizeof(int));
  433.         bcopy(buffer+sizeof(int), (char *) &activeBytes, sizeof(int));
  434.         printf("LfsSetSegUsage(%s,%d,%d)\n", lfsPtr->name, 
  435.                 segNumber, activeBytes);
  436.         LfsSetSegUsage(lfsPtr, segNumber, activeBytes);
  437.         } else {
  438.         status = GEN_INVALID_ARG;
  439.         }
  440.  
  441.         return status;
  442.     }
  443.     case FS_ZERO_ASPLOS_STATS_LFS_COMMAND: {/* For ASPLOS only.  Remove when
  444.                             * that's done. -Mary 2/15/92. */
  445.         /*
  446.          * Zero the stats used for asplos measurements.  We've gotta
  447.          * run this once per file system  before removing the stats so that
  448.          * the checkpoint copies of the padding bytes will be zeroed again.
  449.          */
  450.         status = GetDomainFromCmdArgs(&bufSize, &buffer, &domainPtr);
  451.         if (status != SUCCESS) {
  452.         return status;
  453.         }
  454.         lfsPtr = (Lfs *) domainPtr->clientData;
  455.         bzero((char *) &(lfsPtr->stats.log.fsyncWrites),
  456.             sizeof(LfsStatsCounter));
  457.         bzero((char *) &(lfsPtr->stats.log.fsyncPartialWrites),
  458.             sizeof(LfsStatsCounter));
  459.         bzero((char *) &(lfsPtr->stats.log.fsyncBytes),
  460.             sizeof(LfsStatsCounter));
  461.         bzero((char *) &(lfsPtr->stats.log.fsyncPartialBytes),
  462.             sizeof(LfsStatsCounter));
  463.         bzero((char *) &(lfsPtr->stats.log.partialWriteBytes),
  464.             sizeof(LfsStatsCounter));
  465.         bzero((char *) &(lfsPtr->stats.log.cleanPartialWriteBytes),
  466.             sizeof(LfsStatsCounter));
  467.         bzero((char *) &(lfsPtr->stats.log.fileBytesWritten),
  468.             sizeof(LfsStatsCounter));
  469.         bzero((char *) &(lfsPtr->stats.log.cleanFileBytesWritten),
  470.             sizeof(LfsStatsCounter));
  471.         bzero((char *) &(lfsPtr->stats.log.partialFileBytes),
  472.             sizeof(LfsStatsCounter));
  473.  
  474.         bzero((char *) &(lfsPtr->stats.layout.descLayoutBytes),
  475.             sizeof(LfsStatsCounter));
  476.         
  477.         bzero((char *) &(lfsPtr->stats.dirlog.cleaningBytesWritten),
  478.             sizeof(LfsStatsCounter));
  479.  
  480.         break;
  481.     }
  482.     case FS_TOGGLE_ASPLOS_STATS_LFS_COMMAND: {/* Just for ASPLOS. */
  483.         /*
  484.          * Toggle on or off the taking of Lfs ASPLOS stats. The last time
  485.          * these stats are taken, they must be turned off and then
  486.          * zeroed with the above command.
  487.          */
  488.         Lfs_DoASPLOSStats = 1 - Lfs_DoASPLOSStats;
  489.         status = SUCCESS;
  490.         break;
  491.     }
  492.     default: {
  493.         status = GEN_INVALID_ARG;
  494.     }
  495.     }
  496.     return status;
  497. }
  498.  
  499. /*
  500.  *----------------------------------------------------------------------
  501.  *
  502.  * CheckpointCallBack --
  503.  *
  504.  *    A Proc_CallFunc for checkpoint LFS file systems.
  505.  *
  506.  * Results:
  507.  *    None
  508.  *
  509.  * Side effects:
  510.  *    None.
  511.  *
  512.  *----------------------------------------------------------------------
  513.  */
  514. static void
  515. CheckpointCallBack(clientData, callInfoPtr)
  516.     ClientData       clientData;        /* Lfs structure of LFS */
  517.     Proc_CallInfo    *callInfoPtr;
  518. {
  519.  
  520.     CheckPointData *cpDataPtr = (CheckPointData *) clientData;
  521.     Lfs    *lfsPtr = cpDataPtr->lfsPtr;
  522.  
  523.     if (cpDataPtr->interval > 0) {
  524.     (void) LfsCheckPointFileSystem(lfsPtr, LFS_CHECKPOINT_TIMER);
  525.     callInfoPtr->interval = cpDataPtr->interval;
  526.     } else if (cpDataPtr->interval == 0) {
  527.     free((char *) cpDataPtr);
  528.     callInfoPtr->interval = 0;
  529.     } else {
  530.     callInfoPtr->interval = -cpDataPtr->interval;
  531.     }
  532. }
  533.  
  534. /*
  535.  *----------------------------------------------------------------------
  536.  *
  537.  * LfsLogBase2 --
  538.  *
  539.  *    Compute the log base 2 of the given integer. The argument is assumed
  540.  *    to have only one bit set in it.
  541.  *
  542.  * Results:
  543.  *    Log base 2 of the integer.
  544.  *
  545.  * Side effects:
  546.  *
  547.  *----------------------------------------------------------------------
  548.  */
  549.  
  550. int
  551. LfsLogBase2(val)
  552.     unsigned    int    val;    /* Value of take log of. */
  553. {
  554.     register int     bit;
  555.  
  556.     for (bit = 0; bit < sizeof(val)*8; bit++) {
  557.     if (val & (1 << bit)) {
  558.         break;
  559.     }
  560.     }
  561.     if (val != (1 << bit)) {
  562.     panic("LfsLogBase2: Botched computation of %d\n", val);
  563.     }
  564.     return bit;
  565. }
  566.  
  567. /*
  568.  *----------------------------------------------------------------------
  569.  *
  570.  * LfsError --
  571.  *
  572.  *    Print an error message.
  573.  *
  574.  * Results:
  575.  *    None.
  576.  *
  577.  * Side effects:
  578.  *    None.
  579.  *
  580.  *----------------------------------------------------------------------
  581.  */
  582.  
  583. void
  584. LfsError(lfsPtr, status, message)
  585.     Lfs    *lfsPtr;
  586.     ReturnStatus status;
  587.     char *message;
  588. {
  589.     panic("LfsError: on %s status 0x%x, %s\n", lfsPtr->name, status, message);
  590. }
  591.  
  592.  
  593.